package com.liaoyifan.core.aspect;

import com.liaoyifan.core.annotation.RateLimit;
import com.liaoyifan.core.enums.CoreCodeEnum;
import com.liaoyifan.core.exception.ResultException;
import com.liaoyifan.core.util.Redis;
import com.liaoyifan.core.util.SpELKey;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;

@SuppressWarnings("unused")
@Aspect
@Order(2)
public class RateLimitAspect {

    private static final Logger log = LogManager.getLogger(RateLimitAspect.class.getSimpleName());

    @SuppressWarnings("unused")
    @Around("@annotation(rateLimit)")
    public Object rateLimitAround(ProceedingJoinPoint joinPoint, RateLimit rateLimit)
            throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String key =
                SpELKey.rateLimitKey(
                        signature, joinPoint.getArgs(), rateLimit.value(), rateLimit.isSpEL());
        log.info("RateLimitKey: {}", key);
        if (!Redis.tryAcquire(key, rateLimit.allowed(), 1, 1, rateLimit.timeout())) {
            throw new ResultException(CoreCodeEnum.RATE_LIMIT_EXCEEDED);
        }
        return joinPoint.proceed();
    }
}
